package com.anivia.system.auth.service.impl;

import cn.dev33.satoken.stp.SaLoginModel;
import cn.hutool.core.util.StrUtil;
import com.anivia.common.core.constant.NumberConstant;
import com.anivia.common.core.constant.TableFieldConstant;
import com.anivia.common.core.enums.PlatformTypeEnum;
import com.anivia.common.core.exception.BusinessException;
import com.anivia.common.core.util.AssertUtil;
import com.anivia.common.core.util.BeanUtil;
import com.anivia.common.web.satoken.admin.StpAdminUtil;
import com.anivia.common.web.satoken.tenant.StpTenantUtil;
import com.anivia.common.web.satoken.user.StpUserUtil;
import com.anivia.common.web.satoken.util.UserInfoUtil;
import com.anivia.system.auth.enums.SwitchStatusEnum;
import com.anivia.system.auth.mapper.UserInfoMapper;
import com.anivia.system.auth.model.dto.UserInfoAddOrUpdateDTO;
import com.anivia.system.auth.model.dto.UserInfoLoginDTO;
import com.anivia.system.auth.model.entity.UserInfoDO;
import com.anivia.system.auth.model.vo.UserLoginVO;
import com.anivia.system.auth.service.IUserInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 用户基础信息 服务实现类
 * </p>
 *
 * @author wangj
 * @since 2024-04-02
 */
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfoDO> implements IUserInfoService {
    @Resource
    private PasswordEncoder passwordEncoder;

    @Override
    public void addOrUpdate(UserInfoAddOrUpdateDTO dto) {
        boolean existsPhone = this.lambdaQuery()
                .eq(UserInfoDO::getPhone, dto.getPhone())
                .eq(UserInfoDO::getType, PlatformTypeEnum.ADMIN)
                .ne(dto.getId() != null, UserInfoDO::getId, dto.getId())
                .exists();
        AssertUtil.isFalse(existsPhone, "手机号已存在");

        UserInfoDO userInfoDO = null;
        if (dto.getId() == null) {
            userInfoDO = BeanUtil.newBean(dto, UserInfoDO.class);
            userInfoDO.setPassword(passwordEncoder.encode(dto.getPassword()));
        } else {
            userInfoDO = this.getById(dto.getId());
            AssertUtil.notNull(userInfoDO, "用户不存在");

            BeanUtil.copyProperties(dto, userInfoDO);

            if (StrUtil.isNotBlank(userInfoDO.getPassword())) {
                userInfoDO.setPassword(passwordEncoder.encode(dto.getPassword()));
            }
        }

        userInfoDO.setType(PlatformTypeEnum.ADMIN);
        this.saveOrUpdate(userInfoDO);
    }

    @Override
    public UserLoginVO login(UserInfoLoginDTO dto) {
        // 查询用户
        UserInfoDO userInfo = this.lambdaQuery()
                .eq(UserInfoDO::getType, dto.getUserType())
                .eq(UserInfoDO::getPhone, dto.getPhone())
                .one();
        AssertUtil.notNull(userInfo, "用户不存在");
        AssertUtil.isTrue(SwitchStatusEnum.ENABLE.equals(userInfo.getStatus()), "手机号已被禁用");

        // 校验验证码、密码等
        switch (dto.getLoginType()) {
            case TYPE_1 -> {
                boolean matches = passwordEncoder.matches(dto.getPassword(), userInfo.getPassword());
                AssertUtil.isTrue(matches, "密码错误");
            }
            case TYPE_2 -> throw new BusinessException("手机号验证码模式暂不可用"); // TODO
            default -> throw new BusinessException("登录方式错误");
        }
        // 登录
        UserLoginVO userLoginVO = new UserLoginVO();
        SaLoginModel saLoginModel = new SaLoginModel();
        switch (dto.getUserType()) {
            case ADMIN -> {
                // a端租户id= -1
                saLoginModel.setExtra(TableFieldConstant.TENANT_ID, NumberConstant.MINUS_ONE);
                StpAdminUtil.login(userInfo.getId(), saLoginModel);
                userLoginVO.setToken(StpAdminUtil.getTokenValue());
            }
            case TENANT -> {
                saLoginModel.setExtra(TableFieldConstant.TENANT_ID, userInfo.getTenantId());
                StpTenantUtil.login(userInfo.getId(), saLoginModel);
                userLoginVO.setToken(StpTenantUtil.getTokenValue());
            }
            case USER -> {
//                TODO
            }
            default -> throw new BusinessException("用户类型错误");
        }
        return userLoginVO;
    }

    @Override
    public void logout() {
        if (StpAdminUtil.isLogin()) {
            StpAdminUtil.logout(StpAdminUtil.getTokenValue());
        }
        if (StpTenantUtil.isLogin()) {
            StpTenantUtil.logout(StpAdminUtil.getTokenValue());
        }
        if (StpUserUtil.isLogin()) {
            StpUserUtil.logout(StpAdminUtil.getTokenValue());
        }
    }

    @Override
    public UserLoginVO userInfo() {
        UserInfoDO userInfo = this.lambdaQuery()
                .eq(UserInfoDO::getId, UserInfoUtil.getLoginUserId())
                .one();
        AssertUtil.notNull(userInfo, "用户不存在");

        UserLoginVO userLoginVO = new UserLoginVO();
        userLoginVO.setPhone(userInfo.getPhone());
        userLoginVO.setUserName(userInfo.getUserName());
        return userLoginVO;
    }
}
